package com.sghd.candy.module.shop.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.sghd.candy.module.account.manager.Account;
import com.sghd.candy.module.account.manager.AccountManager;
import com.sghd.candy.module.bag.manager.PlayerBag;
import com.sghd.candy.module.bag.manager.PlayerBagManager;
import com.sghd.candy.module.box.manager.PlayerBoxManager;
import com.sghd.candy.module.common.event.PushEvent;
import com.sghd.candy.module.element.manager.PlayerElementManager;
import com.sghd.candy.module.player.manager.Player;
import com.sghd.candy.module.player.manager.PlayerManager;
import com.sghd.candy.module.player.manager.PlayerOther;
import com.sghd.candy.module.shop.manager.ShopConfig;
import com.sghd.candy.module.shop.manager.ShopManager;
import com.sghd.candy.module.skill.manager.PlayerSkillManager;
import com.sghd.common.event.EventBus;
import com.sghd.pojo.candy.bag.enums.PropType;
import com.sghd.pojo.candy.box.enums.KeyType;
import com.sghd.pojo.candy.shop.enums.ConsumeType;
import com.sghd.pojo.candy.shop.vo.ShopVo;
import com.sghd.pojo.fight.game.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

import static com.sghd.candy.utils.SocketEnum.BAG_INFO;
import static com.sghd.pojo.StaticConfig.*;

/**
 * @author Allen
 * @date 2019/01/09
 */
@Service
public class ShopService {
    private static final Logger logger = LoggerFactory.getLogger(ShopService.class);
    @Autowired
    private ShopManager shopManager;
    @Autowired
    private PlayerBagManager playerBagManager;
    @Autowired
    private PlayerBoxManager playerBoxManager;
    @Autowired
    private PlayerManager playerManager;
    @Autowired
    private AccountManager accountManager;
    @Autowired
    private PlayerSkillManager playerSkillManager;
    @Autowired
    private PlayerElementManager playerElementManager;
    @Autowired
    private EventBus eventBus;

    public List<ShopVo> list(Player player){
        List<ShopVo> shopVoList = new ArrayList<>(1);
        List<ShopConfig> shopConfigList = shopManager.list();

        PlayerOther playerOther = playerManager.loadOther(player.getPlayerId());
        Map<String, Integer> limitMap = playerOther.getValue(OTHER_BUY_LIMIT, new TypeReference<Map<String, Integer>>(){});

        for (ShopConfig shopConfig : shopConfigList) {
            /*ShopVo shopVo = ShopVo.valueOf(shopConfig.getId(), shopConfig.getShopModule(),
                    shopConfig.getConsume(), shopConfig.getConsumeType(), shopConfig.getObtain());*/
            ShopVo shopVo = ShopVo.valueOf(shopConfig.getId());
            if (shopConfig.getBuyLimit() > 0) {
                if (limitMap != null && limitMap.size() != 0) {
                    int buyCount = limitMap.getOrDefault(shopConfig.getId(),0);
                    if (buyCount >= shopConfig.getBuyLimit()) {
                        shopVo.setCanBuy(false);
                    }
                }
            }
            shopVoList.add(shopVo);
        }
        return shopVoList;
    }

    public Result<String> buy(Player player, String shopId) {
        Account account = accountManager.load(player.getId());
        if (account.isGuest()) {
            return Result.valueOf(-1,"游客部分功能受限！");
        }

        ShopConfig shopConfig = shopManager.load(shopId);
        if (shopConfig == null) {
            if (logger.isDebugEnabled()) {
                logger.debug("玩家[{}]购买商品[{}]不存在！",player.getPlayerId(), shopId);
            }
            return Result.valueOf(-1,"商品不存在！");
        }

        if (shopConfig.getBuyLimit() > 0) {
            PlayerOther playerOther = playerManager.loadOther(player.getPlayerId());
            Map<String, Integer> limitMap = playerOther.getValue(OTHER_BUY_LIMIT, new TypeReference<Map<String, Integer>>(){});
            if (limitMap != null && limitMap.size() != 0) {
                int buyCount = limitMap.getOrDefault(shopConfig.getId(),0);
                if (buyCount >= shopConfig.getBuyLimit()) {
                    return Result.valueOf(-1,"购买次数超上限！");
                }
            }
        }

        switch (shopConfig.getConsumeType()) {
            case RMB:
                return Result.SUCCESS();
            case DIAMOND:
            case GOLD:
                return exchange(player, shopConfig);
            default:
                return Result.valueOf(-1,"参数错误！");
        }
    }

    public com.sghd.common.utils.model.Result<String> recharge(Player player, ShopConfig shopConfig) {
        obtain(player, shopConfig.getObtain());
        if (shopConfig.getBuyLimit() > 0) {
            PlayerOther playerOther = playerManager.loadOther(player.getPlayerId());
            Map<String, Integer> limitMap = playerOther.getValue(OTHER_BUY_LIMIT, new TypeReference<Map<String, Integer>>(){});
            if (limitMap == null) {
                limitMap = new HashMap<>(1);
            }
            limitMap.put(shopConfig.getId(),limitMap.getOrDefault(shopConfig.getId(),0) + 1);
            playerManager.update(playerOther, OTHER_BUY_LIMIT, limitMap);
        }
        return com.sghd.common.utils.model.Result.SUCCESS();
    }

    private Result<String> exchange(Player player, ShopConfig shopConfig) {
        PlayerBag playerBag = playerBagManager.getPlayerBag(player.getPlayerId());
        if (shopConfig.getConsumeType() == ConsumeType.DIAMOND) {
            if (playerBag.getDiamond() >= shopConfig.getConsume()) {
                playerBagManager.change(playerBag, PropType.DIAMOND,-1 * shopConfig.getConsume());
            } else {
                return Result.valueOf(-1,"钻石不足");
            }
        } else if (shopConfig.getConsumeType() == ConsumeType.GOLD) {
            if (playerBag.getMoney() >= shopConfig.getConsume()) {
                playerBagManager.change(playerBag, PropType.MONEY,-1 * shopConfig.getConsume());
            } else {
                return Result.valueOf(-1,"金币不足");
            }
        } else {
            return Result.valueOf(-1,"参数错误！");
        }

        obtain(player, shopConfig.getObtain());
        return Result.SUCCESS();
    }

    private void obtain(Player player, Map obtain) {
        Set<String> keys = obtain.keySet();
        for (String key : keys) {
            switch (key) {
                case SHOP_INCLUDE_PROP:
                    Map<String, Integer> propMap = (Map) obtain.get(SHOP_INCLUDE_PROP);
                    propMap.forEach((propId, count) ->
                            playerBagManager.change(playerBagManager.getPlayerBag(player.getPlayerId()),
                                    PropType.values()[Integer.parseInt(propId)], count)
                    );
                    break;
                case SHOP_INCLUDE_BOXKEY:
                    Map<String, Integer> boxKeyMap = (Map) obtain.get(SHOP_INCLUDE_BOXKEY);
                    boxKeyMap.forEach((keyId, count) ->
                            playerBoxManager.change(playerBoxManager.getPlayerBox(player.getPlayerId()),
                                    KeyType.values()[Integer.parseInt(keyId)], count)
                    );
                    break;
                case SHOP_INCLUDE_DEBRIS:
                    int debris = (int) obtain.get(SHOP_INCLUDE_DEBRIS);
                    playerSkillManager.change(playerSkillManager.getPlayerSkill(player.getPlayerId()), debris);
                    break;
                case SHOP_INCLUDE_DIANSHU:
                    int dianShu = (int) obtain.get(SHOP_INCLUDE_DIANSHU);
                    playerElementManager.change(playerElementManager.getPlayerElement(player.getPlayerId()), dianShu);
                    break;
                default:
            }
        }

        PlayerBag playerBag = playerBagManager.getPlayerBag(player.getPlayerId());
        Map<Integer, Long> propMap = new HashMap(2);
        propMap.put(PropType.MONEY.ordinal(), playerBag.getMoney());
        propMap.put(PropType.DIAMOND.ordinal(), playerBag.getDiamond());
        eventBus.post(PushEvent.valueOf(propMap, player.getPlayerId(), BAG_INFO));
    }
}
